package com.meatball.authorization.config

import com.meatball.authorization.config.filter.JwtAuthenticationFilter
import com.meatball.authorization.config.handler.CustomAccessDeniedHandler
import com.meatball.authorization.config.handler.CustomAuthenticationEntryPoint
import com.meatball.authorization.service.RoleService
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.DependsOn
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter


@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@DependsOn("dataInitializer")
class SecurityConfiguration(
        private val jwtAuthFilter: JwtAuthenticationFilter,
        private val authenticationProvider: AuthenticationProvider,
        private val logoutHandler: LogoutComponent,
        private val roleService: RoleService
) {

    @Bean
    fun securityFilterChain(http: HttpSecurity) : SecurityFilterChain {
        return http
                .csrf { it.disable() } // 关闭跨域
                .authorizeHttpRequests {
                    it.requestMatchers(
                            "/api/auth/**",
                            "/swagger-ui/**",
                            "/v3/**",
                            "/swagger-ui.html",
                            "/doc.html",
                            "/webjars/**",
                            "/favicon.ico"
                    ).permitAll()
                    // 配置需要权限访问的路径
                    // requestMatchers: 指定需要拦截的路径
                    // hasAnyAuthority: 指定需要的权限
//                    it.requestMatchers("/api/management/**").hasAnyRole(RoleEnum.ADMIN.name, RoleEnum.MANAGER.name, RoleEnum.USER.name)
                    it.requestMatchers("/api/management/**").hasAnyRole(*roleService.findAllRoles().toTypedArray())
                    // 设置所有的请求都需要验证
                    it.anyRequest().authenticated()
                }
                .sessionManagement {
                    // 使用无状态Session
                    it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                }
                .authenticationProvider(authenticationProvider)
                // 添加jwt过滤器
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter::class.java)
                .logout {
                    it.logoutUrl("/api/auth/logout")
                            .addLogoutHandler(logoutHandler)
                            .logoutSuccessHandler { _, _, _ -> SecurityContextHolder.clearContext() }
                }
                .exceptionHandling {
                    it.authenticationEntryPoint(CustomAuthenticationEntryPoint())
                    it.accessDeniedHandler(CustomAccessDeniedHandler())
                }
                .build()
    }
}